package com.dylan.channel.v11.option;

import com.dylan.channel.v11.constant.Constant;
import com.dylan.util.ObjectUtil;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

/***
 * @Author dylan
 * @Description: Constant常量池
 * @Create: 2024/9/18 10:57
 */
public abstract class ConstantPool<T extends Constant<T>> {

    private final ConcurrentHashMap<String,T>constants = new ConcurrentHashMap<>();

    /**
     * @Author: PP-jessica
     * @Description:初始化常量类的id，初值为1
     */
    private final AtomicInteger nextId = new AtomicInteger(1);

    /**
     * @Author: PP-jessica
     * @Description:该方法也是创建常量的方法
     */
    public T valueOf(String name) {
        checkNotNullAndNotEmpty(name);
        return getOrCreate(name);
    }
    /**
     * @Author: PP-jessica
     * @Description:该方法虽然被标注为废弃的了，但是仍然在被使用，所以我也没有删掉它
     */
    @Deprecated
    public final int nextId() {
        return nextId.getAndIncrement();
    }
    /**
     * @Author: PP-jessica
     * @Description:真正创建常量类的方法，这里的参数就是常量的名字，创建的常量是以key-name，value-ChannelOption<T>的形式
     * 存储在map中的
     */
    private T getOrCreate(String name) {
        T constant = constants.get(name);
        //先判断常量池中是否有该常量
        if (constant == null) {
            //没有的话就创建
            final T tempConstant = newConstant(nextId(), name);
            //然后放进常量池中
            constant = constants.putIfAbsent(name, tempConstant);
            if (constant == null) {
                return tempConstant;
            }
        }
        //最后返回该常量
        return constant;
    }

    private static String checkNotNullAndNotEmpty(String name) {
        ObjectUtil.checkNotNull(name, "name");
        if (name.isEmpty()) {
            throw new IllegalArgumentException("empty name");
        }
        return name;
    }
    /**
     * @Author: PP-jessica
     * @Description:终于又看到一个抽象方法了，把该方法设置为抽象的，立刻就应该想到该抽象类有不止一个实现子类，ChannelOption只是其中之一
     */
    protected abstract T newConstant(int id, String name);
}
